/*
 * Copyright 2011 Dominik Pretzsch <dominik.pretzsch at gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.blacksheep.jmoteextract.progress;

import java.util.concurrent.LinkedBlockingDeque;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Dominik Pretzsch <dominik.pretzsch at gmail.com>
 */
public class ProgressUpdateQueue {
    
    private static LinkedBlockingDeque<ProgressUpdateQueueObject> QUEUE;
    private static ProgressUpdateQueue INSTANCE;
    
    private static final Logger LOGGER = Logger.getLogger(ProgressUpdateQueue.class.getName());
    
    private class ProgressUpdateQueueObject {
        private int type;
        private Object[] data;

        public ProgressUpdateQueueObject(int type, Object[] data) {
            this.type = type;
            this.data = data;
        }
        
        public int getType() {
            return this.type;
        }
        
        public Object[] getData() {
            return this.data;
        }
        
        public Object[] getTypeDataBundled() {
            return new Object[] {
                this.type,
                this.data
            };
        }
    }

    private ProgressUpdateQueue() {
        QUEUE = new LinkedBlockingDeque<ProgressUpdateQueueObject>();
    }
    
    public static ProgressUpdateQueue getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new ProgressUpdateQueue();
        }
        return INSTANCE;
    }
    
    public void enqueue(int type, Object[] data) {
        LOGGER.log(Level.FINE, "Try to enqueue type {0}...", type);
        
        ProgressUpdateQueueObject puqo;
        puqo = new ProgressUpdateQueueObject(type, data);
        
        QUEUE.addLast(puqo);
        
        synchronized (this) {
            notify();
        }
    }
    
    public Object[] dequeue() {
        LOGGER.log(Level.FINE, "Try to dequeue...");
        
        ProgressUpdateQueueObject puqo = null;
        
        /*if (QUEUE.isEmpty()) {
            LOGGER.log(Level.FINE, "... queue is empty. Wait...");
            synchronized (this) {
                try {
                    wait();
                } catch (InterruptedException ex) {
                    LOGGER.log(Level.SEVERE, null, ex);
                }
            }
        }        
        LOGGER.log(Level.FINE, "... dequeuing...");*/
        
        try {
            puqo = (ProgressUpdateQueueObject) QUEUE.takeFirst();
        } catch (InterruptedException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
        }
        
        Object[] typeDataBundle = null;
        
        if (puqo != null) {
            LOGGER.log(Level.FINE, "Dequeuing successfull, getTypeDataBundled()...");
            typeDataBundle = puqo.getTypeDataBundled();
        }
        
        return typeDataBundle;
    }
}
